package com.uyaer.engine.plug
{
	import com.uyaer.engine.Const;
	import com.uyaer.engine.Engine;
	import com.uyaer.engine.Globle;
	import com.uyaer.engine.event.EventManager;
	import com.uyaer.engine.event.EventType;
	import com.uyaer.engine.event.MyEvent;
	
	import flash.events.EventDispatcher;
	import flash.events.KeyboardEvent;

	public class Keybord
	{
		private static var cacheCode:Array = new Array();
		private static var runCache:Object = null;
		private static var isMoveKeyUp:Boolean = true;
		private static var isRuning:Boolean = false;
		private static var keyPress:Object = {};
		private static var currDir:int = 0;
		public function Keybord()
		{
			Engine.instance.stage.addEventListener(KeyboardEvent.KEY_UP,keyUpHandler);
			Engine.instance.stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
			EventManager.addEvent(EventType.KEYBORDSTOP,keyBordStop);
		}
		
		private function keyBordStop(e:MyEvent):void{
			isRuning = false;
		}
		
		private function keyDownHandler(e:KeyboardEvent):void{
			var code:int = e.keyCode;
			var time:Number = new Date().time;
			switch(code)
			{
				case 37://←
					currDir = Const.LEFT;
					break;
				case 38://↑
					currDir = Const.TOP;
					break;
				case 39://右
					currDir = Const.RIGHT;
					break;
				case 40://↓
					currDir = Const.BOTTOM;
					break;
				case 65://A
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL0);
					break;
				case 83://S
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL1);
					break;
				case 68://D
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL2);
					break;
				case 70://F
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL3);
					break;
				case 71://G
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL4);
					break;
				case 81://Q
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL5);
					break;
				case 87://W
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL6);
					break;
				case 69://E
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL7);
					break;
				case 82://R
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL8);
					break;
				case 84://T
					EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL9);
					break;
				case 86://V
					EventManager.dispatchEvent(EventType.FIND);
					break;
				case 90: //Z
					if(isMoveKeyUp){ //没有方向键，发射特殊攻击，方向按照人物现在的方向
						EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL0);
					}else{ //有方向，检测是否可以进行技能播放
						checkTimeout(time);//如果时间没有超过，并且能够进行连招
						var skill:int = checkSkill();
						if(skill > Const.NONE){
							EventManager.dispatchEvent(EventType.USESKILL,skill);
						}else{
							EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL0);
						}
					}
					//不管如何都清除按键缓存
					cacheCode = new Array();
					break;
				case 88: //X
					if(isMoveKeyUp){
						EventManager.dispatchEvent(EventType.ATTACK);
					}else{
						if(checkIsRun(code,time) && (currDir == Const.LEFT || currDir == Const.RIGHT)){ //处于奔跑状态，则进行奔跑攻击
							EventManager.dispatchEvent(EventType.USESKILL,Const.SKILL_RUN);
						}else{
							EventManager.dispatchEvent(EventType.ATTACK);
						}
					}
					break;
				case 67: //C
					EventManager.dispatchEvent(EventType.JUMP);
					break;
			}
			if(code == 37 || code == 38 || code == 39 || code == 40){
				if(code == 37 || code == 39){
					if(checkIsRun(code,time)){
						isRuning = true;
						EventManager.dispatchEvent(EventType.RUN,currDir);
					}else{
						isRuning = false;
						EventManager.dispatchEvent(EventType.MOVE,currDir);
					}
				}else{
					if(isRuning){
						EventManager.dispatchEvent(EventType.RUN,currDir);
					}else{
						isRuning = false;
						EventManager.dispatchEvent(EventType.MOVE,currDir);
					}
				}
				isMoveKeyUp = false;
			}else{
				currDir = Const.NONE;
			}
		}
		
		private function keyUpHandler(e:KeyboardEvent):void{
			var code:int = e.keyCode;
			keyPress[code] = false;
			var time:Number = new Date().time;
			switch(code)
			{
				case 37://←
					addCacheCode(Const.LEFT ,new Date().time);
					runCache = {"dir":Const.LEFT,"time":time};
					break;
				case 38://↑
					addCacheCode(Const.TOP ,new Date().time);
					runCache = {"dir":Const.TOP,"time":time};
					break;
				case 39://右
					addCacheCode(Const.RIGHT ,new Date().time);
					runCache = {"dir":Const.RIGHT,"time":time};
					break;
				case 40://↓
					addCacheCode(Const.BOTTOM ,new Date().time);
					runCache = {"dir":Const.BOTTOM,"time":time};
					break;
			}
			if(code == 37 || code == 38 || code == 39 || code == 40){
				isMoveKeyUp = true;
				EventManager.dispatchEvent(EventType.STOP,runCache.dir);
			}
		}
		
		/**
		 *检测是否可以使用技能 
		 * @return 
		 * 
		 */		
		private static function checkSkill():int{
			var res:int = currDir;
			if(currDir > Const.NONE){
				for(var i:int = 0 ; i < cacheCode.length ; i++ ){
					res += cacheCode[i].code;
				}
				var skill:int = SkillTree.findSkill(res);
				if(skill>Const.NONE){
					return skill;
				}
			}
			return Const.NONE;
		}
		
		/**
		 *添加按键缓存 
		 * @param code
		 * @param time
		 * 
		 */		
		private static function addCacheCode(code:int,time:Number):void{
			checkTimeout(time);
			cacheCode.push({"code":code , "time":time});
			if(cacheCode.length > 2){
				cacheCode.shift();
			}
		}
		
		/**
		 *检测按键是否过期 
		 * @param time
		 * @return 
		 * 
		 */		
		private static function checkTimeout(time:Number):void{
			if(cacheCode.length>0){
				var last:Object = cacheCode[cacheCode.length-1];
				if(time - last.time > Globle.delayTime){ //时间超过，清空缓存键
					cacheCode = new Array();
				}
			}
		}
		
		/**
		 *检测是否是奔跑状态 
		 * @param time
		 * @return 
		 * 
		 */		
		private static function checkIsRun(code:int, time:Number):Boolean{
			if(runCache && (Math.abs(time - runCache.time) < Globle.delayTime || isRuning) 
				&& runCache.dir == currDir){
				return true;
			}
			return false;
		}
	}
}